﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using S9Engine;
using System.Data.Objects;
using System.Linq.Expressions;
using System.IO;
using System.Text;

namespace S9Engine
{
    public class Parser : System.Web.UI.Page
    {
        #region Declare Variables & Contructor

        private const string DEFAULT_PAGES = "Category.aspx,Ajax.aspx,Search.aspx";

        public S9Engine _parser;
        public DinorichEntities _DR;
        public string _currentLanguage;
        public string _currentPage;
        public string _webcmsPath;
        public int _rowsPerPage;
        public int _rowsNewsPerPage;
        public int _pageRange;
        public long _id;        
        public long _cid;
        public long _pid;
        public long _nid;
        public int _quantity;
        public double _price;

        public Func<long, int, List<CategoryList>> BuildListCategory;

        public Parser()
        {
            _parser = new S9Engine();
            _DR = new DinorichEntities();
        }

        #endregion Declare Variables & Contructor

        #region Init File

        public void LoadFile(string filePath, bool ajax)
        {
            InitAll();
            _parser.LoadFile(filePath);
            if (!ajax) AssignCommon();
        }

        public void InitAll()
        {
            if (string.IsNullOrEmpty(Session["Language"] as string)) Session["Language"] = _parser.GetConfig("DefaultLanguage", "VN");

            if (Request["id"] != null) _id = long.Parse(Request["id"].ToString() ?? "0");
            if (Request["cid"] != null) _cid = long.Parse(Request["cid"].ToString() ?? "0");
            if (Request["pid"] != null) _pid = long.Parse(Request["pid"].ToString() ?? "0");
            if (Request["nid"] != null) _nid = long.Parse(Request["nid"].ToString() ?? "0");

            _webcmsPath = _parser.GetConfig("webcmsPath", "~/../webcms");
            _currentPage = (Session["CurrentPage"].ToString() ?? string.Empty).ToLower();
            _currentLanguage = Session["Language"].ToString();
            _rowsPerPage = int.Parse(_parser.GetConfig("RowsPerPage", "5"));
            _rowsNewsPerPage = int.Parse(_parser.GetConfig("RowsNewsPerPage", "6"));
            _pageRange = int.Parse(_parser.GetConfig("PageRange", "5"));

            GetCategoryID(_cid);

            _parser.Assign("cid", _cid.ToString());
            _parser.Assign("pid", _pid.ToString());
            _parser.Assign("nid", _nid.ToString());
            _parser.Assign("currentPath", Request.RawUrl);
            _parser.Assign("userLoginName", (Session["Fullname"] ?? string.Empty).ToString());
            _parser.Assign("totalVisited", Application["TotalVisit"].ToString() ?? "1");
            _parser.Assign("totalOnline", Application["TotalOnline"].ToString() ?? "1");            
            _parser.Assign("currentLanguage", _currentLanguage);
            _parser.Assign("webcmsPath", _webcmsPath);

            LoadSetting();
        }

        private void LoadSetting()
        {
            List<Meta> metas = _DR.Meta.Where(m => m.Type.Equals("setting-" + _currentLanguage)).ToList();

            foreach (Meta m in metas)
            {
                _parser.Assign(m.Key, m.Value);
            }
        }

        private void AssignCommon()
        {                       
            LoadMultiLevelCategory("MainMenu", "MainMenu", "Category.aspx", "last", "current");
            LoadMultiLevelCategory("ProductMenu", "ProductMenu", "Category.aspx", "last", "current");
            LoadLastestNews(5, "News", false);
            LoadAdvertise("Main", "Advertise");
            LoadAdvertise("Main", "Customer");
            
            //LoadCategoryByPosition("BottomMenu", "BottomMenu", "current", "last");
            //LoadCategoryByPosition("TopMenu", "TopMenu", "current", "last");
            //LoadAdvertise("Main", "HomeBanner");
            //LoadAdvertise("Main", "Advertise");
            //LoadAdvertise("Main", "Affiliate");
            
            //LoadAllGallery();
            //GalleryRoom();
            //LoadSearchCategory("Main.SearchCategory");
            //LoadCart();            
        }
        

        #endregion Init File

        #region Other Functions

        private void CheckLogin()
        {
            if (Session["IsLogged"] != null && Session["IsLogged"].ToString() == "True")
            {
                string accountName = Session["AccountName"].ToString() ?? "Khách";

                long accountID = long.Parse(Session["AccountID"].ToString() ?? "0");
                bool exist=false;

                if (accountID != 0)
                {
                   exist = _DR.Users.Where(u => u.ID.Equals(accountID)).Count() > 0;
                }

                if (!exist || accountID == 0)
                {
                    Session["IsLogged"] = "False";
                    Session["AccountName"] = string.Empty;
                    Session["AccountID"] = "0";

                    _parser.Parse("Main.IsNotLogged");
                }
                else
                {
                    _parser.Assign("accountName", accountName);
                    _parser.Parse("Main.IsLogged");
                }
            }
            else
            {
                _parser.Parse("Main.IsNotLogged");
            }
        }

        public string AssignWebCmsPath(string content)
        {
            return content.Replace("uploads", _webcmsPath + "/uploads");
        }

        public void GetCategoryID(long ID)
        {
            if (ID != 0) return;

            if (DEFAULT_PAGES.IndexOf(Session["CurrentPage"].ToString()) == -1)
            {
                long categoryID = _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryURL") && m.Value.ToLower().Equals(_currentPage)).Select(m => m.Object).FirstOrDefault();

                _cid = categoryID;
            }
        }

        public void BuildCategory(List<CategoryList> categoryList)
        {
            BuildListCategory = (ParentId, Level) =>
            {
                return (from c in categoryList
                        where c.Parent == ParentId
                        from t in new List<CategoryList>()
                        {
                            new CategoryList()
                            {
                                ID = c.ID,
                                Name = new String('-', Level).Replace("-", "&mdash;") + c.Name,
                                URL = c.URL,
                                Image = c.Image,
                                Parent = c.Parent,
                                Level = Level,
                                Last = c.Last,
                                Current = c.Current
                            }
                        }.Union(BuildListCategory(c.ID, Level + 1))
                        select t).ToList();
            };
        }

        private List<CategoryList> PrepareCategory(string positionCode, string categoryType, string page, bool orderByParent)
        {
            long position = _DR.Positions.Where(p => p.LanguageCode.Equals(_currentLanguage) && p.Code.Equals(positionCode)).Select(p => p.ID).FirstOrDefault();

            List<CategoryList> categories = (from term in _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage))
                                             join metaURL in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryURL")) on term.ID equals metaURL.Object
                                             join metaImage in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryImage")) on term.ID equals metaImage.Object
                                             join taxonomy in _DR.Taxonomy.Where(tx => (string.IsNullOrEmpty(categoryType) || tx.Name.Equals(categoryType))) on term.ID equals taxonomy.Term
                                             join relation in _DR.Relations.Where(r => r.Type.Contains(categoryType + "-position") && r.Parent.Equals(position)) on term.ID equals relation.Child
                                             orderby relation.Order
                                             select new CategoryList()
                                             {
                                                 ID = term.ID,
                                                 Name = term.Name,
                                                 URL = metaURL.Value ?? string.Empty,
                                                 Image = metaImage.Value ?? string.Empty,
                                                 Parent = taxonomy.Parent,
                                                 Level = 0,
                                                 Last = false,
                                                 Current = false
                                             }).ToList();

            if (categories.Count == 0) return null;

            categories[categories.Count - 1].Last = true;

            //long currentID = long.Parse(categories.Where(c => ((string.IsNullOrEmpty(c.URL) && (_cid == c.ID)) || c.URL.Equals(_currentPage))).Select(c => c.ID.ToString()).FirstOrDefault() ?? "-1");

            categories = categories.Select(t => new CategoryList()
            {
                ID = t.ID,
                Name = t.Name,
                Image = t.Image,
                URL = t.URL,
                Parent = categories.Where(t2 => t2.ID == t.Parent).Count() > 0 ? t.Parent : 0,
                Level = t.Level,
                Last = t.Last,
                Current = t.ID.Equals(_cid) ? true : false
            }).ToList();

            if (!orderByParent) return categories;

            BuildCategory(categories);
            categories = BuildListCategory(0, 0);

            long parentID = categories.Where(c => c.ID.Equals(_cid)).Select(c => c.Parent).FirstOrDefault();

            int groupIndex = 0;

            if (parentID != 0)
            {
                groupIndex = categories.Where(c => c.Parent == 0).ToList().IndexOf(categories.Where(c => c.ID.Equals(parentID)).FirstOrDefault());
            }
            else
            {
                groupIndex = categories.Where(c => c.Parent == 0).ToList().IndexOf(categories.Where(c => c.ID.Equals(_cid)).FirstOrDefault());
            }

            _parser.Assign("groupIndex", groupIndex.ToString());

            return categories;
        }

        private List<CategoryList> PrepareCategory(string positionCode, string page, bool orderByParent)
        {
            long position = _DR.Positions.Where(p => p.LanguageCode.Equals(_currentLanguage) && p.Code.Equals(positionCode)).Select(p => p.ID).FirstOrDefault();

            List<CategoryList> categories = (from term in _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage))
                                             join metaURL in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryURL")) on term.ID equals metaURL.Object
                                             join metaImage in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryImage")) on term.ID equals metaImage.Object
                                             join taxonomy in _DR.Taxonomy on term.ID equals taxonomy.Term
                                             join relation in _DR.Relations on term.ID equals relation.Child
                                             orderby relation.Order
                                             select new CategoryList()
                                             {
                                                 ID = term.ID,
                                                 Name = term.Name,
                                                 URL = metaURL.Value ?? string.Empty,
                                                 Image = metaImage.Value ?? string.Empty,
                                                 Parent = taxonomy.Parent,
                                                 Level = 0,
                                                 Last = false,
                                                 Current = false,
                                                 CategoryType=taxonomy.Name
                                             }).ToList();

            if (categories.Count == 0) return null;

            categories[categories.Count - 1].Last = true;

            //long currentID = long.Parse(categories.Where(c => ((string.IsNullOrEmpty(c.URL) && (_cid == c.ID)) || c.URL.Equals(_currentPage))).Select(c => c.ID.ToString()).FirstOrDefault() ?? "-1");

            categories = categories.Select(t => new CategoryList()
            {
                ID = t.ID,
                Name = t.Name,
                Image = t.Image,
                URL = t.URL,
                Parent = categories.Where(t2 => t2.ID == t.Parent).Count() > 0 ? t.Parent : 0,
                Level = t.Level,
                Last = t.Last,
                Current = t.ID.Equals(_cid) ? true : false
            }).ToList();

            if (!orderByParent) return categories;

            BuildCategory(categories);
            categories = BuildListCategory(0, 0);

            long parentID = categories.Where(c => c.ID.Equals(_cid)).Select(c => c.Parent).FirstOrDefault();

            int groupIndex = 0;

            if (parentID != 0)
            {
                groupIndex = categories.Where(c => c.Parent == 0).ToList().IndexOf(categories.Where(c => c.ID.Equals(parentID)).FirstOrDefault());
            }
            else
            {
                groupIndex = categories.Where(c => c.Parent == 0).ToList().IndexOf(categories.Where(c => c.ID.Equals(_cid)).FirstOrDefault());
            }

            _parser.Assign("groupIndex", groupIndex.ToString());

            return categories;
        }

        public IEnumerable<CategoryList> GetParents(IEnumerable<CategoryList> categoryList, long parentID)
        {
            var current = categoryList.Where(c => c.ID.Equals(parentID)).FirstOrDefault();

            if (current == null) return Enumerable.Empty<CategoryList>();

            return Enumerable.Concat(new[] { current }, GetParents(categoryList, current.Parent));
        }

        public List<CategoriesList> GetCategoriesIDs()
        {
            return _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage)).Join(_DR.Taxonomy, t => t.ID, tx => tx.Term, (t, tx) => new CategoriesList { ID = t.ID, Parent = tx.Parent, Name = t.Name }).ToList();
        }

        public IEnumerable<CategoriesList> GetBreadCrumb(List<CategoriesList> categories, long parentID)
        {
            var current = categories.Where(c => c.ID.Equals(parentID)).FirstOrDefault();

            if (current == null) return Enumerable.Empty<CategoriesList>();

            return Enumerable.Concat(new[] { current }, GetBreadCrumb(categories, current.Parent));
        }

        public string GetRequest(string key)
        {
            return Request[key] == null ? string.Empty : Server.UrlDecode(Request[key].ToString());
        }

        public string GetRequest(string key, string defaultValue)
        {
            return Request[key] == null ? defaultValue : Server.UrlDecode(Request[key].ToString() ?? defaultValue);
        }

        public void WriteError(Exception ex)
        {
            try
            {
                _parser.Assign("errorCode", "Error:" + ex.ToString() ?? ex.Message);
            }
            catch (Exception ex2)
            {
                Response.ContentType = "text/html";
                Response.Write(ex.ToString() + ex2.ToString());
            }
        }

        public bool IsNullValues(params object[] values)
        {
            foreach (object o in values)
            {
                if (o == null) return true;
            }

            return false;
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            writer.Write(_parser._outContent);
        }

        #endregion Other Functions

        #region Load News

        public void LoadNewsByCategoryURL(string urlName, string containBlock, bool isHot, bool paging)
        {
            var news = (from term in _DR.Terms
                        join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                        join meta in _DR.Meta.Where(m => m.Key.Equals("CategoryURL") && m.Value.Equals(urlName)) on term.ID equals meta.Object
                        join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                        join post in _DR.Posts.Where(p => p.Type.Equals("news")) on relation.Child equals post.ID
                        join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                        join metaPostImage in _DR.Meta.Where(m => m.Key.Equals("NewsImage")) on post.ID equals metaPostImage.Object
                        join metaPostImageThumb in _DR.Meta.Where(m => m.Key.Equals("NewsImageThumbnail")) on post.ID equals metaPostImageThumb.Object
                        orderby post.ID descending
                        select new NewsList()
                        {
                            ID = post.ID,
                            Title = post.Title,
                            Excerpt = post.Excerpt,
                            Content = post.Content,
                            Date = post.Date,
                            Image = metaPostImage.Value,
                            ImageThumbnail = metaPostImageThumb.Value,
                            CategoryID = 0,
                            CategoryName = string.Empty,
                        }).ToList();

            if (news == null) return;

            string currentCategoryName = _DR.Terms.Where(t => t.ID.Equals(_cid)).Select(t => t.Name).FirstOrDefault();
            string currentCategoryImage = _DR.Meta.Where(m => m.Type.Equals("category") && m.Object.Equals(_cid) && m.Key.Equals("CategoryImage2")).Select(m => m.Value).FirstOrDefault() ?? string.Empty;

            _parser.Assign("currentCategoryImage", currentCategoryImage);

            if (paging)
            {
                ParseNewsListWithPaging(news, containBlock, _cid.ToString(), currentCategoryName);
            }
            else
            {
                ParseNewsList(news, containBlock, _cid.ToString(), currentCategoryName);
            }

            news = null;
        }

        public void LoadAllNewsByCategoryID(long ID, string containBlock, bool isHot, int noOfNews)
        {
            string currentCategoryName = _DR.Terms.Where(t => t.ID.Equals(ID)).Select(t => t.Name).FirstOrDefault();
            _parser.Assign("currentCategoryName", currentCategoryName);

            List<NewsList> news = (from term in _DR.Terms.Where(t => t.ID.Equals(ID))
                                   join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                                   join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                                   join post in _DR.Posts.Where(p => p.Type.Equals("news")) on relation.Child equals post.ID
                                   //join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                                   join metaPostImage in _DR.Meta.Where(m => m.Key.Equals("NewsImage")) on post.ID equals metaPostImage.Object into Imagefun
                                   from mimage in Imagefun.DefaultIfEmpty()
                                   join metaPostImageThumb in _DR.Meta.Where(m => m.Key.Equals("NewsImageThumbnail")) on post.ID equals metaPostImageThumb.Object into ImageThumfun
                                   from mimagethumb in ImageThumfun.DefaultIfEmpty()
                                   join metaPostAuthor in _DR.Meta.Where(m => m.Key.Equals("Author")) on post.ID equals metaPostAuthor.Object into Authorfun
                                   from mAuthor in Authorfun.DefaultIfEmpty()
                                   join metaPostDocument in _DR.Meta.Where(m => m.Key.Equals("Document")) on post.ID equals metaPostDocument.Object into Documentfun
                                   from mDocument in Documentfun.DefaultIfEmpty()                                   
                                   select new NewsList()
                                   {
                                       ID = post.ID,
                                       Title = post.Title,
                                       Excerpt = post.Excerpt,
                                       Content = post.Content,
                                       Author=mAuthor.Value,
                                       Order=relation.Order,
                                       Document=mDocument.Value,
                                       Date = post.Date,
                                       CategoryID = ID,
                                       CategoryName = currentCategoryName,
                                       Image = mimage.Value,
                                       ImageThumbnail = mimagethumb.Value
                                   }).DistinctBy(n=>n.ID).OrderByDescending(p=>p.Date).ThenBy(p=>p.Order).ToList();

            if (news.Count==1)
            {
                Response.Redirect("news.aspx?nid=" + news[0].ID + "&cid=" + news[0].CategoryID);
                return;
            }
            //ParseNewsList(news, containBlock, ID.ToString(), currentCategoryName);
            ParseNewsListWithPaging(news, containBlock, ID.ToString(), currentCategoryName);
        }

        public void LoadNewsByCategoryID(long ID, string containBlock, bool isHot)
        {
            Posts news = (from term in _DR.Terms.Where(t => t.ID.Equals(ID))
                          join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                          join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                          join post in _DR.Posts.Where(p => p.Type.Equals("news")) on relation.Child equals post.ID
                          join meta in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals meta.Object
                          select post).FirstOrDefault();

            if (news == null) return;

            string currentCategoryName = _DR.Terms.Where(t => t.ID.Equals(ID)).Select(t => t.Name).FirstOrDefault();
            string currentCategoryImage = _DR.Meta.Where(m => m.Type.Equals("category") && m.Object.Equals(ID) && m.Key.Equals("CategoryImage2")).Select(m => m.Value).FirstOrDefault() ?? string.Empty;

            _parser.Assign("currentCategoryName", currentCategoryName);
            _parser.Assign("currentCategoryImage", currentCategoryImage);
            _parser.Assign("categoryID", ID.ToString());

            _parser.Assign("newsID", news.ID.ToString());
            _parser.Assign("currentNewsTitle", news.Title);
            _parser.Assign("currentNewsContent", AssignWebCmsPath(news.Content));
            _parser.Assign("newsDate", news.Date.ToShortDateString());

            _parser.Parse(string.Format("Main.{0}", containBlock));

            news = null;
        }

        public void LoadNewsByCategoryPosition(int noOfNews, string positionCode, string containBlock, bool isHot)
        {
            List<NewsList> news = new List<NewsList>();

            if (noOfNews == 0)
            {
                news = (from post in _DR.Posts.Where(p => p.LanguageCode.Equals(_currentLanguage))
                        join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                        join relation1 in _DR.Relations.Where(r => r.Type.Equals("news-category")) on post.ID equals relation1.Child
                        join term in _DR.Terms on relation1.Parent equals term.ID
                        join relation2 in _DR.Relations.Where(r => r.Type.Equals("news-category-position")) on term.ID equals relation2.Child
                        join position in _DR.Positions on relation2.Parent equals position.ID
                        where position.Code.Equals(positionCode)
                        orderby post.ID descending
                        select new NewsList()
                        {
                            ID = post.ID,
                            Title = post.Title,
                            Excerpt = post.Excerpt,
                            Date = post.Date,
                            CategoryID = term.ID,
                            CategoryName = term.Name
                        }).ToList();
            }
            else
            {
                news = (from post in _DR.Posts.Where(p => p.LanguageCode.Equals(_currentLanguage))
                        join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                        join relation1 in _DR.Relations.Where(r => r.Type.Equals("news-category")) on post.ID equals relation1.Child
                        join term in _DR.Terms on relation1.Parent equals term.ID
                        join relation2 in _DR.Relations.Where(r => r.Type.Equals("news-category-position")) on term.ID equals relation2.Child
                        join position in _DR.Positions on relation2.Parent equals position.ID
                        where position.Code.Equals(positionCode)
                        orderby post.ID descending
                        select new NewsList()
                        {
                            ID = post.ID,
                            Title = post.Title,
                            Excerpt = post.Excerpt,
                            Date = post.Date,
                            CategoryID = term.ID,
                            CategoryName = term.Name
                        }).Take(noOfNews).ToList();
            }

            int index = 0;
            string lastClassText = " class=\"last\"";

            foreach (var item in news)
            {
                index++;

                _parser.Assign("newsID", item.ID.ToString());
                _parser.Assign("categoryID", item.CategoryID.ToString());
                _parser.Assign("newsTitle", item.Title);
                _parser.Assign("categoryName", item.CategoryName);
                _parser.Assign("newsExcerpt", item.Excerpt);
                _parser.Assign("newsDate", item.Date.ToShortDateString());
                _parser.Assign("newsDay", item.Date.Day.ToString());
                _parser.Assign("newsMonth", item.Date.ToString("MMM"));
                _parser.Assign("lastClass", index == news.Count ? lastClassText : string.Empty);

                _parser.Parse(string.Format("Main.{0}.{0}Item", containBlock, containBlock));
            }

            if (news.Count > 0) _parser.Parse(string.Format("Main.{0}", containBlock));
        }

        public void LoadLastestNews(int noOfNews, string mainBlock, bool isHot)
        {
            List<NewsList> news = (from term in _DR.Terms
                                   join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                                   join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                                   join post in _DR.Posts.Where(p => p.Type.Equals("news") && p.LanguageCode.Equals(_currentLanguage)) on relation.Child equals post.ID
                                   join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHome") && m.Value.Equals("True")) on post.ID equals metaNews.Object
                                   join metaPostImage in _DR.Meta.Where(m => m.Key.Equals("NewsImage")) on post.ID equals metaPostImage.Object                                                                      
                                   select new NewsList()
                                   {
                                       ID = post.ID,
                                       Title = post.Title,
                                       Excerpt = post.Excerpt,
                                       Content = post.Content,
                                       Date = post.Date,
                                       CategoryID = term.ID,
                                       CategoryName = term.Name,
                                       Image = metaPostImage.Value,
                                       NewsHome=metaNews.Value
                                      
                                   }).OrderByDescending(p=>p.Date).ThenByDescending(p=>p.ID).Skip(0).Take(noOfNews).ToList();

            ParseNewsList(news, mainBlock, string.Empty, string.Empty);
        }

        public void LoadLastestNews(int noOfNews, long categoryID, string mainBlock, bool isHot)
        {
            List<NewsList> news = (from term in _DR.Terms.Where(t => t.ID == categoryID)
                                   join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                                   join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                                   join post in _DR.Posts.Where(p => p.Type.Equals("news")) on relation.Child equals post.ID
                                   join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                                   join metaPostImage in _DR.Meta.Where(m => m.Key.Equals("NewsImage")) on post.ID equals metaPostImage.Object
                                   join metaPostImageThumb in _DR.Meta.Where(m => m.Key.Equals("NewsImageThumbnail")) on post.ID equals metaPostImageThumb.Object
                                   orderby post.ID descending
                                   select new NewsList()
                                   {
                                       ID = post.ID,
                                       Title = post.Title,
                                       Excerpt = post.Excerpt,
                                       Content = post.Content,
                                       Date = post.Date,
                                       CategoryID = term.ID,
                                       CategoryName = term.Name,
                                       Image = metaPostImage.Value,
                                       ImageThumbnail = metaPostImageThumb.Value
                                   }).Take(noOfNews).ToList();

            ParseNewsList(news, mainBlock, string.Empty, string.Empty);
        }

        public void LoadLastestNews(string mainBlock, bool isHot)
        {
            List<NewsList> news = (from term in _DR.Terms
                                   join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("news-category")) on term.ID equals taxonomy.Term
                                   join relation in _DR.Relations.Where(r => r.Type.Equals("news-category")) on term.ID equals relation.Parent
                                   join post in _DR.Posts.Where(p => p.Type.Equals("news")) on relation.Child equals post.ID
                                   join metaNews in _DR.Meta.Where(m => m.Type.Equals("news") && m.Key.Equals("NewsHot") && (!isHot || m.Value.Equals("on"))) on post.ID equals metaNews.Object
                                   join metaPostImage in _DR.Meta.Where(m => m.Key.Equals("NewsImage")) on post.ID equals metaPostImage.Object
                                   join metaPostImageThumb in _DR.Meta.Where(m => m.Key.Equals("NewsImageThumbnail")) on post.ID equals metaPostImageThumb.Object
                                   orderby post.ID descending
                                   select new NewsList()
                                   {
                                       ID = post.ID,
                                       Title = post.Title,
                                       Excerpt = post.Excerpt,
                                       Content = post.Content,
                                       Date = post.Date,
                                       CategoryID = term.ID,
                                       CategoryName = term.Name,
                                       Image = metaPostImage.Value,
                                       ImageThumbnail = metaPostImageThumb.Value
                                   }).ToList();

            ParseNewsListWithPaging(news, "NewsList", _cid.ToString(), string.Empty);
        }

        public void ParseNewsListWithPaging(List<NewsList> news, string containBlock, string categoryID, string categoryName)
        {
            double totalRecord = news.Count();
            int page = int.Parse(Request["page"] ?? "1");
            int pageSize = _rowsNewsPerPage > totalRecord ? (int)totalRecord : _rowsNewsPerPage;
            int totalPage = (int)(totalRecord / pageSize);

            if (totalPage * pageSize < totalRecord) totalPage++;
            if (totalRecord == 0) { _parser.Parse(string.Format("Main.Noresult")); return;}
            if (totalRecord != 0)
            {
                int startRecord = (page == 1 ? 0 : ((page - 1) * pageSize));
                int endRecord = (int)(page * pageSize > totalRecord ? totalRecord : page * pageSize);

                long startRecordID = news[startRecord].ID;
                long endRecordID = news[endRecord - 1].ID;

                _parser.BeginUpdate(string.Format("Main.{0}.{1}Item", containBlock, containBlock));

                for (int i = startRecord; i < endRecord; i++)
                {
                    _parser.Assign("newsID", news[i].ID.ToString());
                    _parser.Assign("newsTitle", news[i].Title);
                    _parser.Assign("newsExcerpt", news[i].Excerpt);
                    _parser.Assign("categoryName", string.IsNullOrEmpty(categoryName) ? news[i].CategoryName.ToString() : categoryName);
                    _parser.Assign("categoryID", string.IsNullOrEmpty(categoryID) ? news[i].CategoryID.ToString() : categoryID);
                    _parser.Assign("newsImage", news[i].Image);
                    
                    string time = ChangeDayOfWeek(news[i].Date.DayOfWeek.ToString()) + " - " + ZeroNumber(news[i].Date.Day) + "/" + ZeroNumber(news[i].Date.Month) + "/" + news[i].Date.Year.ToString();
                    _parser.Assign("newsDate", time);

                    _parser.Parse(string.Format("Main.{0}.{1}Item", containBlock, containBlock));
                }

                _parser.EndUpdate(string.Format("Main.{0}.{1}Item", containBlock, containBlock));

                _parser.Assign("totalPage", totalPage.ToString());
                _parser.Assign("totalRecord", totalRecord.ToString());
                _parser.Assign("currentPage", page.ToString());
                _parser.Assign("categoryPage", _currentPage.ToLower());

                if (totalPage != 1)
                {
                    int pagingPage = page / _pageRange;
                    int startPage = 1;
                    int endPage = 1;

                    if (page % _pageRange == (_pageRange - 1) && page > _pageRange)
                    {
                        startPage = page;
                    }
                    else
                    {
                        startPage = (pagingPage * _pageRange == 0 ? 1 : pagingPage * _pageRange);
                    }

                    endPage = (startPage + (_pageRange - 1) > totalPage ? totalPage : startPage + (_pageRange - 1));

                    _parser.Assign("pageIndexPrevious", (page == 1 ? 1 : page - 1).ToString());
                    _parser.Assign("pageIndexNext", (page == totalPage ? totalPage : page + 1).ToString());
                    _parser.Assign("categoryID", _cid.ToString());

                    _parser.BeginUpdate(string.Format("Main.{0}.Paging.PagingItem", containBlock));

                    for (int i = startPage; i <= endPage; i++)
                    {
                        _parser.Assign("current", page == i ? " class=\"current\"" : string.Empty);
                        _parser.Assign("pageIndex", i.ToString());

                        _parser.Parse(string.Format("Main.{0}.Paging.PagingItem", containBlock));
                    }

                    _parser.EndUpdate(string.Format("Main.{0}.Paging.PagingItem", containBlock));

                    _parser.Parse(string.Format("Main.{0}.Paging.PagingPrevious", containBlock));
                    _parser.Parse(string.Format("Main.{0}.Paging.PagingNext", containBlock));
                    _parser.Parse(string.Format("Main.{0}.Paging", containBlock));
                }
            }

            _parser.Parse(string.Format("Main.{0}", containBlock));            
            news = null;
        }

        public void ParseNewsList(List<NewsList> news, string containBlock, string categoryID, string categoryName)
        {
            foreach (NewsList n in news)
            {
                _parser.Assign("newsID", n.ID.ToString());
                _parser.Assign("newsTitle", n.Title);
                _parser.Assign("categoryName", string.IsNullOrEmpty(categoryName) ? n.CategoryName.ToString() : categoryName);
                _parser.Assign("categoryID", string.IsNullOrEmpty(categoryID) ? n.CategoryID.ToString() : categoryID);
                _parser.Assign("newsImage", n.Image);
                _parser.Assign("newsDate", n.Date.ToShortDateString());                

                _parser.Parse(string.Format("Main.{0}.{1}Item", containBlock, containBlock));
            }

            if (news.Count > 0) _parser.Parse(string.Format("Main.{0}", containBlock));
            else { _parser.Parse(string.Format("Main.Noresult"));}
        }

        #endregion Load News

        #region Load Category

        private void LoadSearchCategory(string containBlock)
        {
            string htmlCode = string.Empty;

            var categories = (from t in _DR.Terms
                              join tx in _DR.Taxonomy on t.ID equals tx.Term
                              where t.LanguageCode == _currentLanguage && tx.Name == "product-category"
                              from m in _DR.Meta.Where(m => m.Object == t.ID && m.Type == "category" && m.Key == "URL").DefaultIfEmpty()
                              select new
                              {
                                  ID = t.ID,
                                  Parent = tx.Parent,
                                  Level = 0,
                                  Item = new CategoryMenuList()
                                  {
                                      URL = m.Value,
                                      Name = t.Name
                                  }
                              }).ToList().ToHierarchy(c => c.ID, c => c.Parent, c => c.Item, 0, 0);

            string space = string.Empty;

            string categoryID = string.Empty;
            string categoryName = string.Empty;

            for (int i = 0; i < categories.Count(); i++)
            {
                space = new String('.', categories[i].Level).Replace(".", "-");//&mdash;

                categoryID = categories[i].ID.ToString();
                categoryName = (categories[i].Item as CategoryMenuList).Name;

                htmlCode += string.Format("<option value=\"{0}\">{1} {2}</option>", categoryID, space, categoryName);
            }

            _parser.Assign("htmlCode", htmlCode);
            _parser.Parse(containBlock);
        }

        private void LoadAllCategoryHierarchical(string containBlock, string type = "")
        {
            string htmlCode = string.Empty;

            var categories = (from t in _DR.Terms
                              join tx in _DR.Taxonomy on t.ID equals tx.Term
                              where t.LanguageCode == _currentLanguage && (string.IsNullOrEmpty(type) || tx.Name == type)
                              from m in _DR.Meta.Where(m => m.Object == t.ID && m.Type == type && m.Key=="URL").DefaultIfEmpty()
                              select new
                              {
                                  ID = t.ID,
                                  Parent = tx.Parent,
                                  Level = 0,
                                  Item = new CategoryMenuList()
                                  {
                                    URL = m.Value,
                                    Name = t.Name
                                  }
                              }).ToList().ToHierarchy(c => c.ID, c => c.Parent, c => c.Item, 0, 0);

            string closeTags = string.Empty;
            string repeat = string.Empty;
            string categoryType = string.Empty;

            switch(type)
            {
                case "news-category": categoryType="news"; break;
                case "product-category": categoryType = "product"; break;
            }

            string categoryURL = string.Empty;
            string categoryName = string.Empty;

            int currentLevel = -1;
            int tempLevel = 0;
            int lessLevel = 0;

            for (int i = 0; i < categories.Count(); i++)
            {
                tempLevel = categories[i].Level;

                categoryURL = (categories[i].Item as CategoryMenuList).URL;
                categoryURL = string.IsNullOrEmpty(categoryURL) ? "category.aspx?type=" + categoryType + "&cid=" + categories[i].ID.ToString() : categoryURL;
                categoryName = (categories[i].Item as CategoryMenuList).Name;

                if (currentLevel == -1) // First item
                {
                    htmlCode += string.Format("<li><a href=\"{0}\">{1}</a>", categoryURL, categoryName);
                }
                else
                {
                    lessLevel = currentLevel - tempLevel;

                    if (lessLevel == 0) //The same level
                    {
                        htmlCode += string.Format("</li><li><a href=\"{0}\">{1}</a>", categoryURL, categoryName);
                    }
                    else if (lessLevel < 0) //Sub item
                    {
                        htmlCode += string.Format("<ul><li><a href=\"{0}\">{1}</a>", categoryURL, categoryName);
                    }
                    else //Parent item
                    {
                        closeTags = string.Join(string.Empty, Enumerable.Repeat("</ul></li>", (int)lessLevel).ToArray());
                        htmlCode += string.Format("</li>{0}<li><a href=\"{1}\">{2}</a>", closeTags, categoryURL, categoryName);
                    }
                }

                if (i == (categories.Count - 1)) //Last item
                {
                    repeat = htmlCode.Contains("<ul>") ? "</ul></li>" : "";

                    closeTags = string.Join(string.Empty, Enumerable.Repeat(repeat, (int)tempLevel).ToArray());
                    htmlCode += string.Format("</li>{0}", closeTags);
                }

                currentLevel = tempLevel;
            }

            _parser.Assign("htmlCode", htmlCode);
            _parser.Parse("Main." + containBlock);
        }

        public void LoadCategoryByPosition(string containBlock, string positionCode, string categoryType, string currentClass, string lastClass)
        {
            string categoryTypeText = string.Empty;
            string categoryURLText = string.Empty;

            string currentClassText = string.Empty;
            string lastClassText = string.Empty;
            string classText = string.Empty;

            switch (categoryType)
            {
                case "news-category": categoryTypeText = "category.aspx?type=news"; break;
                case "product-category": categoryTypeText = "category.aspx?type=product"; break;
                default: categoryTypeText = "category.aspx?type=news"; break;
            }

            List<CategoryList> categories = PrepareCategory(positionCode, categoryType, categoryTypeText, false);

            _parser.BeginUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

            foreach (CategoryList c in categories)
            {
                categoryURLText = (string.IsNullOrEmpty(c.URL) ? categoryTypeText + "&cid=" + c.ID.ToString() : c.URL).ToLower();

                currentClassText = c.Current ? currentClass : string.Empty;
                lastClassText = c.Last ? lastClass : string.Empty;
                classText = string.Format(" class=\"{0}{1}\"", currentClassText + " ", lastClassText);

                _parser.Assign("categoryID", c.ID.ToString());
                _parser.Assign("categoryName", c.Name.Replace("&mdash;", ""));
                _parser.Assign("categoryImage", c.Image);
                _parser.Assign("categoryURL", categoryURLText);

                _parser.Assign("class", classText);
                _parser.Assign("seperator", c.Last ? string.Empty : "|");

                _parser.Parse(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));
            }

            _parser.EndUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

            _parser.Parse(string.Format("Main.{1}", containBlock, positionCode));
        }

        //public void LoadCategoryByPosition(string containBlock, string positionCode, string currentClass, string lastClass)
        //{
        //    string categoryTypeText = string.Empty;
        //    string categoryURLText = string.Empty;

        //    string currentClassText = string.Empty;
        //    string lastClassText = string.Empty;
        //    string classText = string.Empty;
            

        //    List<CategoryList> categories = PrepareCategory(positionCode, categoryTypeText, false);

        //    _parser.BeginUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

        //    foreach (CategoryList c in categories)
        //    {
        //        categoryTypeText = (c.CategoryType=="news-category")?"category.aspx?type=news": "category.aspx?type=product";
        //        categoryURLText = (string.IsNullOrEmpty(c.URL) ? categoryTypeText + "&cid=" + c.ID.ToString() : c.URL).ToLower();

        //        currentClassText = c.Current ? currentClass : string.Empty;
        //        lastClassText = c.Last ? lastClass : string.Empty;
        //        classText = string.Format(" class=\"{0}{1}\"", currentClassText + " ", lastClassText);

        //        _parser.Assign("categoryID", c.ID.ToString());
        //        _parser.Assign("categoryName", c.Name.Replace("&mdash;", ""));
        //        _parser.Assign("categoryImage", c.Image);
        //        _parser.Assign("categoryURL", categoryURLText);

        //        _parser.Assign("class", classText);
        //        _parser.Assign("seperator", c.Last ? string.Empty : "|");

        //        _parser.Parse(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));
        //    }

        //    _parser.EndUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

        //    _parser.Parse(string.Format("Main.{1}", containBlock, positionCode));
        //}
        public void LoadCategoryByPosition(string containBlock, string positionCode, string currentClass, string lastClass)
        {
            string categoryTypeText = string.Empty;
            string categoryURLText = string.Empty;

            string currentClassText = string.Empty;
            string lastClassText = string.Empty;
            string classText = string.Empty;

            //List<CategoryList> categories = PrepareCategory(positionCode, categoryType, categoryTypeText, false);
            List<CategoryList> categories = PrepareCategory(positionCode, true);

            if (categories == null) return;
            long[] ids = categories.Select(c => c.ID).ToArray();
            List<Taxonomy> taxonomys = _DR.Taxonomy.WhereIn(t => t.Term, ids).Where(t => t.LanguageCode.Equals(_currentLanguage)).ToList();

            _parser.BeginUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

            int i = -1;
            foreach (CategoryList c in categories)
            {
                i++;
                string categoryType = taxonomys.Where(t => t.Term.Equals(c.ID)).Select(t => t.Name).FirstOrDefault();
                string type = (categoryType == "news-category") ? "category.aspx?type=news" : "category.aspx?type=product";
                categoryURLText = string.IsNullOrEmpty(c.URL) ? type + "&cid=" + c.ID.ToString() : c.URL;

                currentClassText = c.Current ? currentClass : string.Empty;
                lastClassText = c.Last ? lastClass : string.Empty;
                classText = string.Format(" class=\"{0}\"", string.Join(" ", new string[] { currentClassText, lastClassText }));

                _parser.Assign("categoryID", c.ID.ToString());
                _parser.Assign("categoryName", c.Name.Replace("&mdash;", ""));
                _parser.Assign("categoryImage", c.Image);
                _parser.Assign("categoryURL", categoryURLText);

                _parser.Assign("class", classText);

                string sperator = (i == categories.Count - 1) ? "" : "|";
                _parser.Assign("seperator", sperator);

                _parser.Parse(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));
            }

            _parser.EndUpdate(string.Format("Main.{1}.{2}Item", containBlock, positionCode, positionCode));

            _parser.Parse(string.Format("Main.{1}", containBlock, positionCode));
        }
        private List<CategoryList> PrepareCategory(string positionCode, bool orderByParent)
        {
            long position = _DR.Positions.Where(p => p.LanguageCode.Equals(_currentLanguage) && p.Code.Equals(positionCode)).Select(p => p.ID).FirstOrDefault();

            List<CategoryList> categories = (from term in _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage))
                                             join relation in _DR.Relations.Where(r => r.Parent.Equals(position) && r.Type.Contains("category-position")) on term.ID equals relation.Child
                                             join taxonomy in _DR.Taxonomy on term.ID equals taxonomy.Term
                                             join meta in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryURL")) on term.ID equals meta.Object
                                             orderby relation.Order
                                             select new CategoryList()
                                             {
                                                 ID = term.ID,
                                                 Name = term.Name,
                                                 Parent = taxonomy.Parent,
                                                 URL = meta.Value,
                                                 Level = 0
                                             }).DistinctBy(t => t.ID).ToList();


            categories = categories.Select(t => new CategoryList()
            {
                ID = t.ID,
                Name = t.Name,
                Parent = categories.Where(t2 => t2.ID == t.Parent).Count() > 0 ? t.Parent : 0,
                URL = t.URL,
                Level = t.Level
            }).ToList();

            if (!orderByParent) return categories;

            BuildCategory(categories);
            categories = BuildListCategory(0, 0);

            return categories;
        }

        public void LoadUlDefault(string parentBlock, string positionCode, string page, string lastClass, string currentClass)
        {
            List<CategoryList> categories = PrepareCategory(positionCode, "product-category", page, true);
            ParseMultiLevelCategoryPosition(categories, parentBlock, page, 1, lastClass, currentClass);
        }

        public void LoadMultiLevelCategory(string parentBlock, string positionCode, string page, string lastClass, string currentClass)
        {
            List<CategoryList> categories = PrepareCategory(positionCode, true);
            ParseMultiLevelCategoryPosition(categories, parentBlock, page, 0, lastClass, currentClass);
        }

        public void ParseMultiLevelCategoryPosition(List<CategoryList> categoryList, string parentBlock, string page, int startIndex, string lastClass, string currentClass)
        {
            long[] ids = categoryList.Select(c => c.ID).ToArray();
            List<Meta> metas = _DR.Meta.WhereIn(c => c.Object, ids).Where(m => m.Type.Equals("category")).ToList();
            List<Taxonomy> taxonomys = _DR.Taxonomy.WhereIn(t => t.Term, ids).Where(t => t.LanguageCode.Equals(_currentLanguage)).ToList();

            string htmlCodeMain = string.Empty;
            string categoryURL = string.Empty;

            string categoryURLText = string.Empty;
            string categoryName = string.Empty;

            bool isCurrentPage = false;
            string currentClassText = string.Empty;
            string lastClassText = string.Empty;
            string closeTags = string.Empty;

            string currentPage = (Session["CurrentPage"].ToString() ?? string.Empty).ToLower();

            long currentLevel = -2;
            long tempLevel = 0;
            long lessLevel = 0;

            for (int i = startIndex; i < categoryList.Count; i++)
            {
                categoryURL = metas.Where(m => m.Object.Equals(categoryList[i].ID) && m.Key.Equals("CategoryURL")).Select(m => m.Value).FirstOrDefault();
                string categoryType = taxonomys.Where(t => t.Term.Equals(categoryList[i].ID)).Select(t => t.Name).FirstOrDefault();
                string type = (categoryType == "news-category") ? "?type=news" : "?type=product";
                categoryURLText = string.IsNullOrEmpty(categoryURL) ? page + type + "&cid=" + categoryList[i].ID.ToString() : categoryURL;
                categoryName = categoryList[i].Name.Replace("&mdash;", "");

                isCurrentPage = ((!string.IsNullOrEmpty(currentPage)) && (categoryURLText.ToLower() == currentPage || categoryURLText.ToLower() == currentPage + "?cid=" + _id.ToString().ToLower()));

                currentClassText = isCurrentPage ? currentClass : string.Empty;
                lastClassText = ((i + 1 == categoryList.Count)) ? lastClass : string.Empty;

                tempLevel = categoryList[i].Level;

                if (currentLevel == -2) // First item
                {
                    htmlCodeMain += string.Format("<li class='{0}'><a href='{1}'>{2}<span></span></a>", currentClassText, categoryURLText, categoryName);
                }
                else
                {
                    lessLevel = currentLevel - tempLevel;

                    if (lessLevel == 0) //The same level
                    {
                        string lClass = (currentClassText != "") ? "" : "last";
                        string span = (tempLevel == 0) ? "<span></span>" : "";
                        htmlCodeMain += string.Format("</li><li class='{0}{1}'><a href='{2}'>{3}{4}</a>", currentClassText, lClass, categoryURLText, categoryName, span);
                    }
                    else if (lessLevel < 0) //Sub item
                    {
                        htmlCodeMain += string.Format("<ul><li class='{0}'><a href='{1}'>{2}</a>", currentClassText, categoryURLText, categoryName);
                    }
                    else //Parent item
                    {
                        closeTags = string.Join(string.Empty, Enumerable.Repeat("</ul></li>", (int)lessLevel).ToArray());
                        htmlCodeMain += string.Format("</li>{0}<li class='{1}'><a href='{2}'>{3}<span></span></a>", closeTags, currentClassText, categoryURLText, categoryName);
                    }
                }

                if (i == (categoryList.Count - 1)) //Last item
                {
                    closeTags = string.Join(string.Empty, Enumerable.Repeat("</ul></li>", (int)tempLevel).ToArray());
                    htmlCodeMain += string.Format("</li>{0}", closeTags);
                }

                currentLevel = tempLevel;
            }

            if (!string.IsNullOrEmpty(htmlCodeMain))
            {
                if (startIndex != 0)
                {
                    _parser.Assign("parentCategoryName", categoryList[0].Name);
                }

                _parser.Assign("htmlCodeMain", htmlCodeMain);
                _parser.Parse(string.Format("Main.{0}", parentBlock));
            }
        }

        public void LoadMultiLevelCategory(string parentBlock, string positionCode, string categoryType, string page, string lastClass, string currentClass)
        {
            List<CategoryList> categories = PrepareCategory(positionCode, categoryType, page, true);

            //ParseMultiLevelCategory(categories, parentBlock, page, 0, lastClass, currentClass);
            ParseMultiLevelCategory(categories, parentBlock, page, 0, lastClass, currentClass, "");
        }
        public void ParseMultiLevelCategory(List<CategoryList> categoryList, string parentBlock, string page, int startIndex, string lastClass, string currentClass, string togClass)
        {
            if (categoryList == null) return;

            long[] ids = categoryList.Select(c => c.ID).ToArray();

            string htmlCode = string.Empty;
            string categoryURL = string.Empty;

            string categoryURLText = string.Empty;
            string categoryName = string.Empty;

            string currentClassText = string.Empty;
            string lastClassText = string.Empty;
            string classText = string.Empty;
            string closeTags = string.Empty;

            long currentLevel = -2;
            long tempLevel = 0;
            long lessLevel = 0;

            for (int i = startIndex; i < categoryList.Count; i++)
            {
                categoryURL = categoryList[i].URL;
                categoryName = categoryList[i].Name.Replace("&mdash;", "");

                //categoryURLText = string.IsNullOrEmpty(categoryURL) ? page + "&cid=" + categoryList[i].ID.ToString() : categoryURL;
                categoryURLText = "";
                categoryURLText = string.IsNullOrEmpty(categoryURL) ? page + "&cid=" + categoryList[i].ID.ToString() : categoryURL;


                currentClassText = categoryList[i].Current ? currentClass + " " : string.Empty;
                lastClassText = categoryList[i].Last ? lastClass : string.Empty;
                classText = string.Format(" class=\"{0}\"", string.Join(" ", new string[] { currentClassText, lastClassText }));

                tempLevel = categoryList[i].Level;

                if (currentLevel == -2) // First item
                {
                    htmlCode += string.Format("<li{0}><a href=\"{1}\">{2}</a>", classText, categoryURLText, categoryName);
                }
                else
                {
                    lessLevel = currentLevel - tempLevel;

                    if (lessLevel == 0) //The same level
                    {
                        htmlCode += string.Format("</li><li{0}><a href=\"{1}\">{2}</a>", classText, categoryURLText, categoryName);
                    }
                    else if (lessLevel < 0) //Sub item
                    {
                        htmlCode += string.Format("<ul class='" + togClass + "'><li{0}><a href=\"{1}\">{2}</a>", classText, categoryURLText, categoryName);
                    }
                    else //Parent item
                    {
                        closeTags = string.Join(string.Empty, Enumerable.Repeat("</ul></li>", (int)lessLevel).ToArray());
                        htmlCode += string.Format("</li>{0}<li{1}><a href=\"{2}\">{3}</a>", closeTags, classText, categoryURLText, categoryName);
                    }
                }

                if (i == (categoryList.Count - 1)) //Last item
                {
                    closeTags = string.Join(string.Empty, Enumerable.Repeat("</ul></li>", (int)tempLevel).ToArray());
                    htmlCode += string.Format("</li>{0}", closeTags);
                }

                currentLevel = tempLevel;
            }

            if (!string.IsNullOrEmpty(htmlCode))
            {
                if (startIndex != 0)
                {
                    _parser.Assign("parentCategoryName", categoryList[0].Name);
                }

                _parser.Assign("htmlCode", htmlCode);
                _parser.Parse(string.Format("Main.{0}", parentBlock));
            }
        }
        #endregion Load Category

        #region Load Data

        public void LoadBanner()
        {
            long id = long.Parse((from t in _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage))
                                  join tx in _DR.Taxonomy.Where(t => t.Name.Equals("gallery-category") && t.Description.Equals("banner")) on t.ID equals tx.Term
                                  select t.ID).FirstOrDefault().ToString() ?? "0");

            var images = (from r in _DR.Relations.Where(r => r.Type.Equals("album-image") && r.Parent.Equals(id))
                          join t in _DR.Terms on r.Parent equals t.ID
                          join i in _DR.Images on r.Child equals i.ID
                          select new
                          {
                              ID = i.ID,
                              URL = i.URL,
                              Link = i.Description
                          }).ToList();

            if (images.Count == 0) return;

            foreach (var image in images)
            {
                _parser.Assign("index", image.ID.ToString());
                _parser.Assign("fileURL", image.URL);
                _parser.Assign("fileName", image.Link);
                _parser.Assign("imageURL", image.Link);

                _parser.Parse("Main.BannerImages.BannerImagesItem");
            }

            if (images.Count > 0) _parser.Parse("Main.BannerImages");
        }

        public void LoadAdvertise(string parentBlock, string positionCode)
        {
            List<Advertises> advertises = (from advertise in _DR.Advertises.Where(a => a.LanguageCode.Equals(_currentLanguage))
                                           join relation in _DR.Relations.Where(r => r.Type.Equals("advertise-position")) on advertise.ID equals relation.Child
                                          join position in _DR.Positions.Where(p => p.LanguageCode.Equals(_currentLanguage)) on relation.Parent equals position.ID
                                          where position.Code.Equals(positionCode)
                                          orderby relation.Order
                                          select advertise).ToList();

            foreach (Advertises a in advertises)
            {
                _parser.Assign("advertiseContent", a.Content);
                _parser.Parse(string.Format("{0}.{1}.{2}Item", parentBlock, positionCode, positionCode));
            }

            if (advertises.Count != 0) _parser.Parse(string.Format("{0}.{1}", parentBlock, positionCode));
        }

        public void LoadMeta(string containBlock, string type, string key)
        {
            var metas = _DR.Meta.Where(m => m.LanguageCode.Equals(_currentLanguage) && m.Type.Equals(type) && m.Key.Equals(key)).Select(m => new { ID = m.ID, Name = m.Value }).ToList();

            foreach (var meta in metas)
            {
                _parser.Assign("metaID", meta.ID.ToString());
                _parser.Assign("metaName", meta.Name);

                _parser.Parse(string.Format("Main.{0}.{1}Item", containBlock, containBlock));
            }

            if (metas.Count > 0) _parser.Parse(string.Format("Main.{0}", containBlock));
        }

        public void LoadGallery(string containBlock, int noOfAlbum)
        {
            var galleries = (from term in _DR.Terms.Where(t => t.LanguageCode.Equals(_currentLanguage))
                            join meta in _DR.Meta.Where(m => m.Type.Equals("category") && m.Key.Equals("CategoryImage")) on term.ID equals meta.Object
                            join taxonomy in _DR.Taxonomy.Where(t => t.Name.Equals("gallery-category") && !t.Description.Equals("banner")) on term.ID equals taxonomy.Term
                            select new
                            {
                                AlbumID = term.ID,
                                AlbumName = term.Name,
                                AlbumImage = meta.Value
                            }).ToList();

            _parser.BeginUpdate(string.Format("Main.{0}.{1}Item", containBlock, containBlock));

            foreach (var album in galleries)
            {
                _parser.Assign("albumID", album.AlbumID.ToString());
                _parser.Assign("albumName", album.AlbumName);
                _parser.Assign("albumImage", album.AlbumImage);

                _parser.Parse(string.Format("Main.{0}.{1}Item", containBlock, containBlock));
            }

            _parser.EndUpdate(string.Format("Main.{0}.{1}Item", containBlock, containBlock));

            if (galleries.Count > 0) _parser.Parse(string.Format("Main.{0}", containBlock));
        }

        public void LoadBreadCrumb(long ID, string containBlock)
        {
            if (ID == 0) return;
            string type = Request["type"];
            if (null == type)
            {
                type = (Request["pid"] == null) ? "news" : "product";
            }
            List<CategoriesList> categoriesList = GetCategoriesIDs();

            categoriesList = GetBreadCrumb(categoriesList, ID).ToList();

            for (int i = categoriesList.Count - 1; i >= 0; i--)
            {
                _parser.Assign("startTag", "<a href=\"category.aspx?type=" + type + "&cid=" + categoriesList[i].ID + "\">");
                _parser.Assign("endTag", "</a>");

                _parser.Assign("breadCrumbName", categoriesList[i].Name);
                _parser.Parse(string.Format("Main.{0}.{1}Item", containBlock, containBlock));
            }

            if (categoriesList.Count > 0) _parser.Parse(string.Format("Main.{0}", containBlock));
        }

        public void LoadCart()
        {
            if (Session["AddToCart"] == null)
            {
                _parser.Assign("totalCartPrice", "0");
                _parser.Assign("totalCartQuantity", "0");
                return;
            }

            List<MyCart> carts = Session["AddToCart"] as List<MyCart>;

            string price = carts.Sum(c => c.Quantity * c.Price).ToString("N0").Replace(',','.');
            string quantity = carts.Sum(c => c.Quantity).ToString();

            _parser.Assign("totalCartPrice", string.IsNullOrEmpty(price) ? "0" : price);
            _parser.Assign("totalCartQuantity", string.IsNullOrEmpty(quantity) ? "0" : quantity);
        }
        public void LoadViewedProduct( string containBlock, string mainBlock)
        {
            if (Request.Cookies["ViewProduct"] == null) _parser.Parse(string.Format("{0}.Noresult", containBlock));
            else {
                string str = Request.Cookies["ViewProduct"].Value;
                str = str.Substring(0, str.Length - 1);
                long[] IDs = str.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(p => long.Parse(p)).Distinct().ToArray();
                var products = (from product in _DR.Products.WhereIn(p => p.ID, IDs)
                                join relation in _DR.Relations.Where(r => r.Type.Equals("product-category")) on product.ID equals relation.Child
                                join term in _DR.Terms on relation.Parent equals term.ID
                                join metaCode in _DR.Meta.Where(m=>m.Type.Equals("product") && m.Key.Equals("Code")) on product.ID equals metaCode.Object
                                join metaSaleWith in _DR.Meta.Where(m=>m.Type.Equals("product") && m.Key.Equals("SaleWithProduct")) on product.ID equals metaSaleWith.Object into metaSaleWithFun
                                from mts in metaSaleWithFun.DefaultIfEmpty()
                                select new { 
                                    ID=product.ID,
                                    CategoryID=term.ID,
                                    Code=metaCode.Value,
                                    Name=product.Name,
                                    Image=product.Image,
                                    Date=product.Date,
                                    SaleProduct=mts.Value
                                }).DistinctBy(p=>p.ID).ToList();
                foreach (var p in products) {
                    _parser.Assign("proID", p.ID.ToString());
                    _parser.Assign("proName", p.Name);
                    _parser.Assign("proCode", p.Code);
                    _parser.Assign("proImage", p.Image);
                    _parser.Assign("proCategoryID", p.CategoryID.ToString());

                    bool newProduct = (DateTime.Now.AddDays(-5) <= p.Date);
                    if (newProduct) _parser.Assign("proNew", "<img alt='Hàng mới' src='../assets/images/icon_new.gif'>");
                    else { _parser.Assign("proNew", ""); }                                        
                    string imgSale = !(string.IsNullOrEmpty(p.SaleProduct)) ? "<img src='../assets/images/icon_discounts.png' alt='Giảm giá' />" : "";
                    if (!string.IsNullOrEmpty(imgSale)) _parser.Assign("ImgSaleView", imgSale);
                                        
                    _parser.Parse(string.Format("{0}.{1}.{2}Item", containBlock, mainBlock, mainBlock));
                }

                _parser.Parse(string.Format("{0}.{1}", containBlock, mainBlock));
            }
        }

        #endregion Load Data

        #region Data Function

        public long AddNewMeta(long objectID, string type, string key, string value, bool saveChange)
        {
            Meta meta = new Meta();

            meta.Object = objectID;
            meta.Type = type;
            meta.Key = key;
            meta.Value = value;
            meta.LanguageCode = _currentLanguage;

            _DR.AddToMeta(meta);

            if (saveChange)
            {
                _DR.SaveChanges();
                return meta.ID;
            }

            meta = null;

            return 0;
        }

        public long AddNewUser(string fullname, string username, string password, string type, bool saveChange)
        {
            Users user = new Users();

            user.Fullname = fullname;
            user.Username = username;
            user.Password = password;
            user.Type = "Customer";
            user.LanguageCode = _currentLanguage;

            _DR.AddToUsers(user);

            if (saveChange)
            {
                _DR.SaveChanges(true);
                return user.ID;
            }

            user = null;
            return 0;
        }

        public bool EditMetaByObject(long objectID, string type, string key, string value, bool saveChange)
        {
            Meta meta = _DR.Meta.Where(m => m.Object.Equals(objectID) && m.Type.Equals(type) && m.Key.Equals(key)).FirstOrDefault();

            if (meta == null) return false;

            meta.Value = value;

            if (saveChange)
            {
                _DR.SaveChanges();
            }

            return true;
        }

        #endregion Data Function

        #region Load Product

        public IEnumerable<ProductList> LoadAllProduct(string metaKey = "", bool isHot=false, bool isHotBeer = true, int noOfProduct = 0)
        {
            string keys = string.Format("{0},HotAlcohol,HotBeer", metaKey);

            var query = (from p in _DR.Products
                         join r in _DR.Relations.Where(r => r.Type.Equals("product-category")) on p.ID equals r.Child
                         join t in _DR.Terms on r.Parent equals t.ID
                         join m in _DR.Meta.Where(m => m.Type == "product" && keys.Contains(m.Key)).Select(m => new ProductMeta() { Object = m.Object, Key = m.Key, Value = m.Value }) on p.ID equals m.Object into meta
                         where p.LanguageCode == _currentLanguage
                         select new ProductList()
                         {
                             ID = p.ID,
                             Parent = t.ID,
                             Date = p.Date,
                             Name = p.Name,
                             Image = p.Image,
                             Price = p.Price,
                             Excerpt=p.Description,
                             Content=p.Content,
                             Manufactory=p.Manufactory,
                             Meta = meta
                         }).OrderByDescending(p=>p.Date).ThenByDescending(p=>p.ID);
                         
            IEnumerable<ProductList> ret = query.ToList().DistinctBy(q => q.ID);

            if (isHot) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotAlcohol" && m.Value == "True").Count() > 0).ToList();
            if (isHotBeer) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotBeer" && m.Value == "True").Count() > 0).ToList();

            if (0 != noOfProduct) ret = ret.Take(noOfProduct).ToList();

            return ret;
        }

        public IEnumerable<ProductList> LoadAllProductByCategoryID(string metaKey = "", bool isHot=false, bool isHotBeer = true,  int noOfProduct = 0, long categoryID=0)
        {
            string keys = string.Format("{0},HotAlcohol,HotBeer", metaKey);

            var query = (from p in _DR.Products
                         join r in _DR.Relations.Where(r => r.Type.Equals("product-category")) on p.ID equals r.Child
                         join t in _DR.Terms.Where(t1 => t1.ID.Equals(categoryID)) on r.Parent equals t.ID
                         join m in _DR.Meta.Where(m => m.Type == "product" && keys.Contains(m.Key)).Select(m => new ProductMeta() { Object = m.Object, Key = m.Key, Value = m.Value }) on p.ID equals m.Object into meta
                         where p.LanguageCode == _currentLanguage
                         orderby p.Date descending
                         select new ProductList()
                         {
                             ID = p.ID,
                             Parent = t.ID,
                             Name = p.Name,   
                             Date=p.Date,
                             Image = p.Image,
                             Price = p.Price,    
                             Excerpt=p.Description,
                             Content=p.Content,
                             Manufactory=p.Manufactory,
                             Meta = meta
                         }).OrderByDescending(p=>p.Date).ThenByDescending(p=>p.ID);

            IEnumerable<ProductList> ret = query.ToList().DistinctBy(q => q.ID);

            if (isHot) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotAlcohol" && m.Value == "True").Count() > 0).ToList();
            if (isHotBeer) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotBeer" && !string.IsNullOrEmpty(m.Value)).Count() > 0).ToList();

            if (0 != noOfProduct) ret = ret.Take(noOfProduct).ToList();

            return ret;
        }
        public IEnumerable<ProductList> LoadAllProducts(string metaKey = "", bool isHot = false, bool isHotBeer = true, int noOfProduct = 0)
        {
            string keys = string.Format("{0},HotAlcohol,HotBeer", metaKey);

            var query = (from p in _DR.Products
                         join r in _DR.Relations.Where(r => r.Type.Equals("product-category")) on p.ID equals r.Child
                         join t in _DR.Terms on r.Parent equals t.ID
                         join m in _DR.Meta.Where(m => m.Type == "product" && keys.Contains(m.Key)).Select(m => new ProductMeta() { Object = m.Object, Key = m.Key, Value = m.Value }) on p.ID equals m.Object into meta
                         where p.LanguageCode == _currentLanguage
                         orderby p.Date descending
                         select new ProductList()
                         {
                             ID = p.ID,
                             Parent = t.ID,
                             Name = p.Name,
                             Date = p.Date,
                             Image = p.Image,
                             Price = p.Price,
                             Excerpt = p.Description,
                             Content = p.Content,
                             Manufactory = p.Manufactory,
                             Quantity=p.Quantity,
                             Meta = meta
                         }).OrderByDescending(p => p.Date).ThenByDescending(p => p.ID);

            IEnumerable<ProductList> ret = query.ToList().DistinctBy(q => q.ID);

            if (isHot) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotAlcohol" && m.Value == "True").Count() > 0).ToList();
            if (isHotBeer) ret = ret.Where(r => r.Meta.Where(m => m.Key == "HotBeer" && !string.IsNullOrEmpty(m.Value)).Count() > 0).ToList();

            if (0 != noOfProduct) ret = ret.Take(noOfProduct).ToList();

            return ret;
        }

        public IEnumerable<ProductList> LoadProductByID(string metaKey = "", bool isHot = false, bool isPromotion = true, long productID = 0)
        {
            string keys = string.Format("{0},Hot,SalePrice,ImageDetail1,ImageDetail2,ImageDetail3,ImageDetail4,WoodMaterial,StoneMaterial", metaKey);

            var query = (from p in _DR.Products.Where(px=>px.ID.Equals(productID))
                         join r in _DR.Relations on p.ID equals r.Child
                         join t in _DR.Terms on r.Parent equals t.ID
                         join m in _DR.Meta.Where(m => m.Type == "product" && keys.Contains(m.Key)).Select(m => new ProductMeta() { Object = m.Object, Key = m.Key, Value = m.Value }) on p.ID equals m.Object into meta
                         where p.LanguageCode == _currentLanguage
                         orderby p.Date descending
                         select new ProductList()
                         {
                             ID = p.ID,
                             Parent = t.ID,
                             Name = p.Name,
                             Date = p.Date,
                             Image = p.Image,
                             Price = p.Price,
                             Excerpt = p.Description,
                             Content = p.Content,
                             Manufactory=p.Manufactory,
                             Meta = meta
                         });

            IEnumerable<ProductList> ret = query.ToList().DistinctBy(q => q.ID);

            if (isHot) ret = ret.Where(r => r.Meta.Where(m => m.Key == "Hot" && m.Value == "True").Count() > 0).ToList();
            if (isPromotion) ret = ret.Where(r => r.Meta.Where(m => m.Key == "SalePrice" && m.Value != "0").Count() > 0).ToList();

            return ret;
        }

        public IEnumerable<GalleryList> LoadAllGallery()
        {          
            var query = (from g in _DR.Rooms.Where(g1=>g1.LanguageCode.Equals(_currentLanguage))                         
                         join d in _DR.RoomDetails.Where(m => m.LanguageCode.Equals(_currentLanguage)).Select(m => new GalleryDetails() {ID=m.ID, Object = m.Object, Type = m.Type, Coordinate=m.Coordinates, Value=m.Value, Content=m.Content, Link=m.Link}) on g.ID equals d.Object into details                         
                         select new GalleryList()
                         {
                             ID = g.ID,
                             GroupName=g.GroupName,
                             Name = g.Name,                             
                             Image = g.Image,
                             Details=details
                         });
            IEnumerable<GalleryList> ret = query.ToList().DistinctBy(q => q.ID);
                        
            return ret;
        }
        public void GalleryRoom() {
            var list = LoadAllGallery().ToList();
            StringBuilder sb = new StringBuilder();
            sb.Append("var imagesCollection = {\"image\": [");
            int i = 0;
            foreach (var g in list) {                
                i++;
                string end=(i==list.Count)?"}": "},";
                sb.Append("{");
                sb.Append("\"id\": "+g.ID.ToString());
                sb.Append(", \"group\": \"" + g.GroupName+"\"");
                sb.Append(", \"name\": \"" + g.Name+"\"");
                sb.Append(", \"src\": \"" + _webcmsPath + g.Image+"\",");
                List<GalleryDetails> dtSpot = g.Details.Where(d=>d.Type.Equals("spot") && d.Object.Equals(g.ID)).ToList();
                List<GalleryDetails> dtArea = g.Details.Where(d => d.Type.Equals("area") && d.Object.Equals(g.ID)).ToList();
                List<GalleryDetails> dtTooltip = g.Details.Where(d => d.Type.Equals("tooltip") && d.Object.Equals(g.ID)).ToList();
                List<GalleryDetails> dtInfo = g.Details.Where(d => d.Type.Equals("info") && d.Object.Equals(g.ID)).ToList();
                
                if (dtSpot.Count > 0) {
                    sb.Append("\"spot\": [");
                    for (int j = 0; j < dtSpot.Count; ++j)
                    {
                        string endDigit = (j == dtSpot.Count - 1) ? "" : ",";
                        sb.Append("{to: " + dtSpot[j].Object + "," + dtSpot[j].Coordinate + ", info: \"" + dtSpot[j].Content + "\"}" + endDigit);
                    }
                    sb.Append("],");
                }
                if (dtArea.Count > 0)
                {
                    sb.Append("\"area\": [");
                    for (int j = 0; j < dtArea.Count; ++j)
                    {
                        string endDigit = (j == dtArea.Count - 1) ? "" : ",";
                        sb.Append("{" + dtArea[j].Coordinate + ", content: \"" + dtArea[j].Content + "\"}" + endDigit);                                                
                    }
                    sb.Append("],");
                }
                if (dtTooltip.Count > 0)
                {
                    sb.Append("\"tooltip\": [");
                    for (int j = 0; j < dtTooltip.Count; ++j)
                    {
                        string endDigit = (j == dtTooltip.Count - 1) ? "" : ",";
                        sb.Append("{" + dtTooltip[j].Coordinate + ", content: \"" + dtTooltip[j].Content + "\"}" + endDigit); 
                    }
                    sb.Append("],");
                }
                if (dtInfo.Count > 0)
                {
                    sb.Append("\"info\": [");
                    for (int j = 0; j < dtInfo.Count; ++j)
                    {
                        string endDigit = (j == dtInfo.Count - 1) ? "" : ",";
                        sb.Append("{id: " + dtInfo[j].ID + ", " + dtInfo[j].Coordinate + ", title: \"" + dtInfo[j].Value + "\", content:\"" + dtInfo[j].Content + "\", url: \"" + dtInfo[j].Link + "\"}" + endDigit);
                    }
                    sb.Append("]");
                }
                sb.Append(end);
            }
            sb.Append("]};");
            string str = sb.ToString();
            File.WriteAllText(Server.MapPath("js/roomgallery.js"), str);
        }
        
        public void LoadAllProduct(string containBlock, string parentBlock, long categoryID)
        {
            var products = LoadAllProductByCategoryID("Code", false, false, 0, categoryID).ToList();
            if (products.Count==0) {
                _parser.Parse(string.Format("{0}.Noresult", containBlock));
                return;
            }
            double totalRecord = products.Count();
            if (totalRecord == 1)
            {
                Response.Redirect("product.aspx?pid=" + products[0].ID + "&cid=" + products[0].Parent);
                return;
            }
            int page = int.Parse(GetRequest("page", "1"));
            int pageSize = _rowsPerPage;
            int totalPage = (int)(totalRecord / pageSize);
            if (totalPage * pageSize < totalRecord) totalPage++;

            if (totalRecord != 0)
            {
                int startRecord = 0;
                int endRecord = (int)(totalRecord);

                if (pageSize != 0)
                {
                    startRecord = (page == 1 ? 0 : ((page - 1) * pageSize));
                    endRecord = (int)(page * pageSize > totalRecord ? totalRecord : page * pageSize);
                }

                for (int i = startRecord; i < endRecord; i++)
                {
                    _parser.Assign("productID", products[i].ID.ToString());
                    _parser.Assign("categoryID", products[i].Parent.ToString());
                    _parser.Assign("productName", products[i].Name);
                    _parser.Assign("productImage", products[i].Image);
                    _parser.Assign("productExcerpt", products[i].Excerpt);
                    
                    //string tmpExcerpt = HttpUtility.HtmlDecode(products[i].Excerpt).Replace("<br />", "");
                    //tmpExcerpt = tmpExcerpt.Substring(4, tmpExcerpt.Length-8);
                    //tmpExcerpt += "/ Hãng sản xuất: " + products[i].Manufactory;
                    //string tmp = HttpUtility.HtmlDecode(products[i].Content).Replace("<br />", "");
                    //tmp = tmp.Substring(3, tmp.Length - 8);
                    //tmpExcerpt += tmp;
                    //tmpExcerpt = tmpExcerpt.Replace("-", "/");
                    //_parser.Assign("productExcerpt", tmpExcerpt);

                    //_parser.Assign("productCode", products[i].Meta.Select(m => m.Key, m => m.Value, "Code"));
                    //string productNew = products[i].Meta.Select(m => m.Key, m => m.Value, "New");
                    //if (productNew.ToLower()=="true") {
                    //    _parser.Parse(string.Format("{0}.{1}.{2}Item.NewProduct", containBlock, parentBlock, parentBlock));
                    //}
                    ////<img src="../assets/images/icon_new.gif" alt="Sản phẩm mới">                    
                    //if (double.Parse(products[i].Meta.Select(m => m.Key, m => m.Value, "SalePrice")) < products[i].Price && 0 != double.Parse(products[i].Meta.Select(m => m.Key, m => m.Value, "SalePrice")))
                    //{
                    //    _parser.Assign("productPrice", products[i].Price.ToString("N0").Replace(',', '.'));
                    //    _parser.Assign("productSalePrice", double.Parse(products[i].Meta.Select(m => m.Key, m => m.Value, "SalePrice")).ToString("N0").Replace(',', '.'));

                    //    _parser.Parse(string.Format("{0}.{1}.{2}Item.SalePrice", containBlock, parentBlock, parentBlock));
                    //}
                    //else
                    //{
                    //    _parser.Assign("productPrice", string.IsNullOrEmpty(products[i].Price.ToString()) ? "Liên hệ" : products[i].Price.ToString("N0").Replace(',', '.') + " VNĐ");
                    //    _parser.Parse(string.Format("{0}.{1}.{2}Item.Price", containBlock, parentBlock, parentBlock));                        
                    //}
                    _parser.Parse(string.Format("{0}.{1}.{2}Item", containBlock, parentBlock, parentBlock));
                }
            }

            if (totalPage != 1 && pageSize != 0)
            {
                int pagingPage = page / 4;
                int startPage = 1;
                int endPage = 1;

                if (page % 4 == (4 - 1) && page > 4)
                {
                    startPage = page;
                }
                else
                {
                    startPage = (pagingPage * 4 == 0 ? 1 : pagingPage * 4);
                }

                endPage = (startPage + (4 - 1) > totalPage ? totalPage : startPage + (4 - 1));

                _parser.Assign("pageIndexPrevious", (page == 1 ? 1 : page - 1).ToString());
                _parser.Assign("pageIndexNext", (page == totalPage ? totalPage : page + 1).ToString());
                _parser.Assign("totalPage", totalPage.ToString());

                for (int i = startPage; i <= endPage; i++)
                {
                    _parser.Assign("pageIndex", i.ToString());

                    _parser.Assign("current", page == i ? "class=\"current\"" : string.Empty);

                    _parser.Parse(string.Format("{0}.{1}.Paging.PagingItem", containBlock, parentBlock));
                }

                _parser.Parse(string.Format("{0}.{1}.Paging", containBlock, parentBlock));
            }

            if (null != products && 0 != products.Count) _parser.Parse(string.Format("{0}.{1}", containBlock, parentBlock));            
        }
        private void LoadSearchManufactory(string containBlock)
        {
            string htmlCode = string.Empty;

            var manufactorys = _DR.Products.Where(p => p.LanguageCode.Equals(_currentLanguage)).DistinctBy(p => p.Manufactory).ToList();
            string manufactory=string.Empty;
            for (int j = 0; j < manufactorys.Count; ++j) {
                manufactory=manufactorys[j].Manufactory;
                htmlCode += string.Format("<option value=\"{0}\">{1}</option>", manufactory, manufactory);
            }            

            _parser.Assign("htmlCode", htmlCode);
            _parser.Parse(containBlock);
        }
        #endregion Load Product
        public void CreateCookie(string key, string value)
        {
            HttpCookie cookie = new HttpCookie(key, value);

            cookie.Expires = DateTime.Now.AddDays(90);
            Response.Cookies.Add(cookie);
        }

        public void DeleteCookie(string key)
        {
            Response.Cookies[key].Expires = DateTime.Now.AddDays(-1);
        }

        public string GetCookie(string key, string defaultValue)
        {
            return Request.Cookies[key] == null ? defaultValue : Request.Cookies[key].Value;
        }
        //public string SetCookie(string key, string value) {            
            //Request.Cookies[key].Value=Request.Cookies[key].Value + value;
            //return Request.Cookies[key].Value + value;
        //}
        ///
        public long AddNewOrder(string fullname, string email, string phone, int quantity, float price, bool saveChange)
        {
            Orders order = new Orders();
            //Votes vote = new Votes();            

            order.Fullname = fullname;
            order.Email = email;
            order.Phone = phone;
            order.Quantity = quantity;
            order.Price = price;
            order.LanguageCode = _currentLanguage;

            _DR.AddToOrders(order);

            if (saveChange)
            {
                _DR.SaveChanges();
                return order.ID;
            }

            order = null;

            return 0;
        }
        //
        public long AddNewRelations(long child, long parent,int order, string type, bool saveChange)
        {
            Relations rel = new Relations();

            rel.Child = child;
            rel.Parent = parent;
            rel.Type = type;
            rel.Order = order;
            rel.LanguageCode = _currentLanguage;

            _DR.AddToRelations(rel);

            if (saveChange)
            {
                _DR.SaveChanges();
                return rel.ID;
            }

            rel = null;

            return 0;
        }
        public bool EditOrderByID(long ID, double value, bool saveChange)
        {
            //Meta meta = _DR.Meta.Where(m => m.Object.Equals(objectID) && m.Type.Equals(type) && m.Key.Equals(key)).FirstOrDefault();
            Orders order = _DR.Orders.Where(o => o.ID.Equals(ID)).FirstOrDefault();

            if (order == null) return false;

            order.Price = value;            

            if (saveChange)
            {
                _DR.SaveChanges();
                order = null;
            }

            return true;
        }

        public long ParentCategoryID(long ID)
        {
            long parentCategoryID = 0;
            long tmpParentID = _DR.Taxonomy.Where(tx => tx.Term.Equals(ID)).Select(t => t.Parent).FirstOrDefault();
            if (tmpParentID == 0) { parentCategoryID = ID; }
            while (tmpParentID != 0)
            {
                parentCategoryID = tmpParentID;
                tmpParentID = _DR.Taxonomy.Where(tx => tx.Term.Equals(tmpParentID)).Select(t => t.Parent).FirstOrDefault();
            }
            return parentCategoryID;
        }

        //
        private void AutoLogin()
        {
            if (IsNullValues(Session["Logged"], Session["Fullname"], Session["UserEmail"]))
            {
                if (null != Request.Cookies["AutoLogin"])
                {
                    bool autoLogin = bool.Parse(GetCookie("AutoLogin", "false"));

                    if (autoLogin)
                    {
                        string username = GetCookie("Username", string.Empty);
                        string password = GetCookie("Password", string.Empty);

                        if (IsNullValues(username, password)) return;

                        Users user;

                        if (IsExistUser(username, password, out user))
                        {
                            Session["Logged"] = true;
                            Session["Fullname"] = user.Fullname;
                            Session["UserEmail"] = username;                            
                            _parser.Parse("Main.LoggedIn");
                        }
                        else
                        {
                            _parser.Parse("Main.LoginForm");
                        }

                        user = null;
                    }
                    else
                    {
                        _parser.Parse("Main.LoginForm");
                    }
                }
                else
                {
                    _parser.Parse("Main.LoginForm");
                }
            }
            else
            {
                _parser.Parse("Main.LoggedIn");
            }
        }
        public bool IsExistUser(string username, string password, out Users user)
        {
            Users userInfo = _DR.Users.Where(u => u.Username.Equals(username) && u.Type.Equals("Customer") && u.Password.Equals(password)).FirstOrDefault();

            user = userInfo;

            return (userInfo != null);
        }
        //private void LoadHotProduct(string parentBlock, string containBlock){
        //    var products = (from product in _DR.Products.Where(p => p.LanguageCode.Equals(_currentLanguage))                            
        //                    join relation in _DR.Relations on product.ID equals relation.Child
        //                    join term in _DR.Terms on relation.Parent equals term.ID
        //                    join meta in _DR.Meta.Where(m => m.Type.Equals("product") && m.Key.Equals("Buy")) on product.ID equals meta.Object into metafun
        //                    from mt in metafun.DefaultIfEmpty()
        //                    orderby mt.Value descending
        //                    select new {
        //                        ID=product.ID,
        //                        CategoryID=term.ID,
        //                        Name=product.Name,
        //                        Image=product.Image,
        //                        NumberBuy=mt.Value
        //                    }).ToList();
        //    if (null == products) _parser.Parse(string.Format("{0}.Noresult",parentBlock));
        //    foreach (var pro in products) {
        //        _parser.Assign("productID", pro.ID.ToString());
        //        _parser.Assign("categoryID", pro.CategoryID.ToString());
        //        _parser.Assign("productImage", pro.Image);

        //        _parser.Parse(string.Format("{0}.{1}.{2}Item",parentBlock, containBlock, containBlock));
        //    }
        //    if (null != products) _parser.Parse(string.Format("{0}.{1}", parentBlock,containBlock));
        //}
        private void LoadHotProduct(string containBlock, string parentBlock)
        {
            var categories = LoadAllProduct("Code", true, false, 9).ToList();

            foreach (var c in categories)
            {
                _parser.Assign("productID", c.ID.ToString());
                _parser.Assign("categoryID", c.Parent.ToString());
                _parser.Assign("productName", c.Name);
                _parser.Assign("productImage", c.Image);
                _parser.Assign("productPrice", c.Price.ToString("N0"));

                _parser.Assign("productCode", c.Meta.Select(m => m.Key, m => m.Value, "Code"));

                _parser.Parse(string.Format("{0}.{1}.{2}Item", containBlock, parentBlock, parentBlock));
            }

            if (null != categories && 0 != categories.Count()) _parser.Parse(string.Format("{0}.{1}", containBlock, parentBlock));
        }
        private string ChangeDayOfWeek(string dayOfWeek)
        {
            string result = "";
            string tmp = dayOfWeek;
            switch (tmp)
            {
                case "Monday": result = "Thứ hai"; break;
                case "Tuesday": result = "Thứ ba"; break;
                case "Wednesday": result = "Thứ tư"; break;
                case "Thursday": result = "Thứ năm"; break;
                case "Friday": result = "Thứ sáu"; break;
                case "Saturday": result = "Thứ bảy"; break;
                case "Sunday": result = "Chủ nhật"; break;
                default: goto case "Monday"; break;
            }
            return result;
        }
        private string ZeroNumber(int value)
        {
            int a = value;
            string s = (a < 10) ? "0" + a.ToString() : a.ToString();
            return s;
        }
    }

    #region Other Classs

    public static class LINQTool
    {
        public static List<HierarchyItem> ToHierarchy<TEntity, TProperty>(this List<TEntity> items, Func<TEntity, TProperty> idProperty, Func<TEntity, TProperty> parentIDProperty, Func<TEntity, object> itemProperty, long parentID, int level) where TEntity : class
        {
            Func<long, int, List<HierarchyItem>> build = null;

            build = (pID, lv) =>
            {
                return (from i in items
                        where parentIDProperty(i).Equals(pID)
                        from h in new List<HierarchyItem>()
                        {
                            new HierarchyItem()
                            {
                                ID = long.Parse(idProperty(i).ToString()),
                                Item = itemProperty(i),
                                Level = lv,
                                Parent = pID
                            }
                        }.Union(build(long.Parse(idProperty(i).ToString()), lv + 1))
                        select h).ToList();
            };

            return build(parentID, level);
        }

        public static string Select<T, TProperty>(this IEnumerable<T> obj, Func<T, TProperty> keyProperty, Func<T, TProperty> valueProperty, string key) where T : class
        {
            var ret = obj.Where(o => keyProperty(o).Equals(key)).Select(o => valueProperty(o)).FirstOrDefault();
            return null == ret ? string.Empty : ret.ToString();
        }        
    }

    public class GalleryDetails {
        public long ID { get; set; }
        public long Object { get; set; }
        public string Type { get; set; }
        public string Coordinate { get; set; }
        public string Value { get; set; }
        public string Content { get; set; }
        public string Link { get; set; }
        public string Language { get; set; }
    }

    public class GalleryList {
        public long ID { get; set; }
        public string GroupName { get; set; }
        public string Name { get; set; }
        public string Image { get; set; }
        public IEnumerable<GalleryDetails> Details { get; set; }
    }

    public class ProductMeta
    {
        public long Object { get; set; }
        public string Key { get; set; }
        public string Value { get; set; }
    }

    public class ProductList
    {
        public long ID { get; set; }
        public long Parent { get; set; }
        public int Quantity { get; set; }
        public string Name { get; set; }
        public double Price { get; set; }        
        public string Image { get; set; }
        public string Excerpt { get; set; }
        public string Content { get; set; }
        public string Manufactory { get; set; }
        public DateTime Date { get; set; }
        public IEnumerable<ProductMeta> Meta { get; set; }
    }

    public class HierarchyItem
    {
        public long ID { get; set; }
        public long Parent { get; set; }
        public int Level { get; set; }
        public object Item { get; set; }
    }

    public class MyCart
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Image { get; set; }
        public int Quantity { get; set; }
        public double Price { get; set; }
    }

    public class CategoryList
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public string URL { get; set; }
        public string Image { get; set; }
        public long Parent { get; set; }
        public long Level { get; set; }
        public bool Last { get; set; }
        public bool Current { get; set; }
        public string CategoryType { get; set; }
    }

    public class NewsList
    {
        public long ID { get; set; }
        public string Title { get; set; }
        public string Excerpt { get; set; }
        public string Content { get; set; }
        public string Author { get; set; }
        public string Document { get; set; }
        public long Order { get; set; }
        public DateTime Date { get; set; }
        public long CategoryID { get; set; }
        public string CategoryName { get; set; }
        public string Image { get; set; }
        public string ImageThumbnail { get; set; }
        public string NewsHome { get; set; }
    }

    public class SearchResult
    {
        public long ID { get; set; }
        public string Title { get; set; }
        public string Excerpt { get; set; }
        public string Content { get; set; }
        public string Type { get; set; }
    }

    public class CategoriesList
    {
        public long ID { get; set; }
        public long Parent { get; set; }
        public string Name { get; set; }
    }

    public class CategoryMenuList
    {
        public string Name { get; set; }
        public string URL { get; set; }
    }

    #endregion Other Classs
}
